                      Machine Language Part VI

                            by Lyle Giese

                          (LYLEG on DELPHI)


Last month I started explaining my SEQ file reader for you. I got up to
putting the opening message on the screen.

Next we must get from you (the user) the filename of the file you want
printed out. We have to start by deciding where we are going to store
the filename. In BASIC, BASIC takes care of that automatically. But of
course that convenience is offset by the slow speed of BASIC.

In this program I decided to use the cassette buffer at $033C. Again I
will use the index and index+1 memory locations to point to the
filename. I will also need another variable for the length of the
filename. For that I used $FD and initialized it by putting a Zero byte
in it.

I issued a call to the KERNAL CLRCHN routine next, just to make sure I
was getting my input from the keyboard. Next call the GETIN routine to
get the keypresses. If no keys are pressed it will return with a zero in
the Accumlator, which the instruction in line 700 checks for.

Next we need to check for the delete key (we don't make typing mistakes
do we?). If we haven't put any characters in the filename, it would be
hard to delete one. So in line 730 & 740 we check to make sure we have
characters there. Then delete the last character printed on the screen
and DECrement the FLEN variable in line 770.

Next we have to check for a carriage return. The carriage return is used
for two things. It will mark the end of the filename after we have typed
it in. Also, we use it to exit the routine. By checking FLEN after
getting a carriage return (in lines 810 & 820), if there are no
characters yet, we exit by the RTS instruction in 830. Or Branch if Not
Equal to the DOPEN routine.

Then if we get to line 840, we have a character we want to add to the
filename. We need to first check the length of the filename before we
add it to the filename. If the filename is too long we really don't want
the extra characters. At this point, we branch back (line 860) to make
you press the return button before trying to find the file.

But 18 characters? Filenames can be only 16 characters long! That's
right, but add the prefix '0:' or '1:' for those of us that have dual
drives and the max length now becomes 18.

I did not check for valid characters by limiting input to numbers and/or
letters only. I only checked for the delete key and the return key. So
that is something to watch out for or a feature for you to add.

Now echo the character to the screen for the you to see and jump back
for more characters to NOKEY, which is at line 690.

After we have finished typing the filename, we need to go to the disk
drive and open a read channel from which to get the characters. But
since we are making a SEQ file reader, I added ',S,R' to the end of the
filename and adjusted FLEN accordingly.

Now, open the command channel to the disk drive so we can see any disk
errors that might occur. That takes us down to line 1090. That checks
for errors opening the error channel.

Now we can open our read channel. We start by setting the filename for
the system with the SETNAM routine. Next the SETLFS and the OPEN
routine. Now we just performed the equivelent of OPEN8,8,8,"FNAM,S,R".
Again go back to your Programmers Reference Guide if you have problems
using the KERNAL routines. Knowing how to read that portion of the PRG
is esstenial to programming in ML on a Commodore computer.

Note in opening the disk channel, I didn't have to remember many
numbers? By using the names (which are defined at the beginning of the
program), I didn't have to remember where I put the filename or where I
put the file length number either. Sure makes it easy to write a program
that way.

Also, what if I made a mistake in placing my filename buffer? If you
didn't use a name for it, you would have to go through the program very
closely changing every reference to it. But here I only have to change
it in one location, in the beginning. It would be very easy to miss one
spot in the program making debugging even harder!

Now that we have done that we must check to make sure that the file was
there and the disk drive properly openned a channel for us. We do that
two ways. The first one actually checks to make sure the computer was
able to properly open the file to the drive. We do that in line 1190.

Next we will read the disk's error channel via a call to the subroutine
CKERROR (line 1210). That takes us to line 4000. We open an input
channel to file #$0F and read the error channel.

If the first two characters out are $30 and $30, that means an error of
00 occured, which of course means no error. Then we would just take all
of the characters out of the error channel to tidy things up and ReTurn
from Subroutine.

If anything else is returned in the first two characters, something went
wrong. Then we want to read and print out the error message on the
screen. That's why we store the first two characters. While printing the
error message, we check for the end of the message by checking for a
carriage return.

Now that we found an error, we can't return to where we were in the
program, because that would lead us down into the file read and print
routines. We want to go back to the beginning of the program.

So in line 4140, we start by printing the disk error message on the
screen to the user. Now we have think about how ML handles a subroutine.
When the JSR instruction is called, the return address has to go
somewhere so that we can find our place when the RTS instruction is
issued. That place is the stack. The 6510 pushes the return address as
two bytes onto the stack.

Since I haven't used the stack for any other storage, it should be the
last two entries on the stack. So we pull two bytes off of the stack and
throw them away. Now this is an advanced technique, but it is important
to understand it. In this case it can be quite handy. But if I had used
the stack for other storage I could not have done this that easily.

At line 4220, we start closing things up by first restoring default I/O
by calling CLRCHN. And then we close the read channel and then the error
channel.

Now I decided to print a short message to indicate I wanted the user to
press the return key and wait for him to press the return key. Why? It
is to give you a chance to read the error message before clearing the
screen when we go back to the beginning of the program.

So at this point we would restart the program. But I have rambled on
enough for one month. Next month we will look at how I handled the
screen or printer option and some of the problems encountered doing
that.

[ED. NOTE: The partial source code to accompany this article is the next
file in this month's edition of the *StarBoard* Journal.]
